﻿using System.Collections.Concurrent;
using System.Text.RegularExpressions;
using CommonTools;
using CommonTools.HttpClient;
using CommonTools.Util;
using Discord.WebSocket;
using Newtonsoft.Json;
using YukariToolBox.LightLog;

namespace Discord.Bot;

/// <summary>
/// 消息处理帮助类
/// </summary>
public class BotUtil
{
    #region 属性

    /// <summary>
    /// 消息 ID 正则
    /// </summary>
    private static readonly string TRIGGER_ID_PATTERN = $@"{DiscordUtil.PROMPT_PREFIX}(\w+?){DiscordUtil.PROMPT_SUFFIX}";

    /// <summary>
    /// 临时存储消息流转信息
    /// </summary>
    private static readonly ConcurrentDictionary<string, bool> _tempMap = new();

    /// <summary>
    /// 回调地址
    /// </summary>
    private static readonly string CALLBACK_URL = AppConfigurationServices.Configuration["DiscordSetting:CALLBACK_URL"];

    #endregion

    #region 方法

    /// <summary>
    /// 获取消息 ID 是否执行
    /// </summary>
    /// <param name="triggerId"></param>
    /// <returns></returns>
    public static (string, bool) GetTemp(string triggerId)
    {
        _tempMap.TryGetValue(triggerId, out bool isFlag);
        return (triggerId, isFlag);
    }

    /// <summary>
    /// 是否包含
    /// </summary>
    /// <param name="triggerId"></param>
    /// <returns></returns>
    public static bool IsExitTemp(string triggerId)
    {
        return _tempMap.ContainsKey(triggerId);
    }

    /// <summary>
    /// 添加消息 ID 执行
    /// </summary>
    /// <param name="triggerId"></param>
    /// <returns></returns>
    public static void SetTemp(string triggerId)
    {
        _tempMap.TryAdd(triggerId, true);
    }

    /// <summary>
    /// 删除消息 ID 
    /// </summary>
    /// <param name="triggerId"></param>
    /// <returns></returns>
    public static void PopTemp(string triggerId)
    {
        (string lTriggerId, bool isFlag) = GetTemp(triggerId);
        _tempMap.TryRemove(new KeyValuePair<string, bool>(lTriggerId, isFlag));
    }

    /// <summary>
    /// 获取消息 ID
    /// </summary>
    /// <param name="content"></param>
    /// <returns></returns>
    public static string MatchTriggerId(string content)
    {
        // 使用Match()匹配
        Match m = Regex.Match(content, TRIGGER_ID_PATTERN);
        if (m.Success)
        {
            return m.Groups.Values.LastOrDefault()?.Value ?? string.Empty;
        }

        return string.Empty;
    }

    /// <summary>
    /// 回调绘画进度
    /// </summary>
    /// <param name="triggerId"></param>
    /// <param name="triggerStatus"></param>
    /// <param name="message"></param>
    /// <returns></returns>
    public static async Task CallBackTrigger(string triggerId, string triggerStatus, IMessage message)
    {
        var param = new CallbackData
        {
            Type = triggerStatus,
            Id = message.Id,
            Content = message.Content,
            AttachmentList = message.Attachments.Select(d => new Attachment
            {
                Id = d.Id,
                Url = d.Url,
                ProxyUrl = d.ProxyUrl,
                FileName = d.Filename,
                ContentType = d.ContentType,
                Width = d.Width ?? 0,
                Height = d.Height ?? 0,
                Size = d.Size,
                Ephemeral = d.Ephemeral
            }).ToList(),
            TriggerId = triggerId
        };
        string data = JsonConvert.SerializeObject(param);
        await CallBack(data);
    }

    /// <summary>
    /// 回调图片会说话
    /// </summary>
    /// <param name="triggerStatus"></param>
    /// <param name="message"></param>
    /// <returns></returns>
    public static async ValueTask<(bool, string)> CallBackDescribe(string triggerStatus, SocketMessage message)
    {
        string url = message.Embeds.FirstOrDefault()?.Url ?? string.Empty;
        if (string.IsNullOrEmpty(url))
        {
            return (false, string.Empty);
        }

        string triggerId = url.Split("/")[^1].Split(".")[0];
        var param = new CallbackData
        {
            Type = triggerStatus,
            Id = message.Id,
            Content = message.Content,
            EmbedList = message.Embeds.Select(d => new Embed
            {
                Type = d.Type.ToString(),
                Description = d.Description,
                Image = d.Image.HasValue ? new EmbedsImage
                {
                    ProxyUrl = d.Image.Value.ProxyUrl,
                    Url = d.Image.Value.Url
                } : new()
            }).ToList(),
            TriggerId = triggerId
        };
        string data = JsonConvert.SerializeObject(param);
        await CallBack(data);
        return (true, triggerId);
    }

    /// <summary>
    /// 回调http请求
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    private static async Task CallBack(string data)
    {
        Log.Debug("Discord", $"callback data: {data}");

        if (string.IsNullOrEmpty(CALLBACK_URL))
        {
            return;
        }

        await HttpClientHelper.SendAsync(CALLBACK_URL, HttpMethod.Post, data, string.Empty);
    }

    #endregion


}